package mapeo;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.ProjectionList;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.transform.AliasToEntityMapResultTransformer;
import org.hibernate.transform.Transformers;

import entidades.Documento;
import entidades.Posteo;
import entidades.Vocabulario;

public class MapPosteo implements IBaseDatos{

	private Session session;
	private Transaction transaction;
	private Posteo posteo;
	
	public MapPosteo(){
		session = null;
		posteo = null;
	}
	
	public Object save(Object objGuardar){
		session = HibernateUtil.getSessionFactory().openSession();
		transaction = null;
		try{
			posteo = (Posteo) objGuardar;
		}
		catch(ClassCastException e){
			System.out.println("ERROR: No se puede castear el objeto a Posteo");
			return null;
		}
		try {
			transaction = session.beginTransaction();
			session.save(posteo);
			transaction.commit();
		} catch (HibernateException e) {
			System.out.println("ERROR: Hibernate no puede realizar el grabado del Posteo");
			transaction.rollback();
			return null;
		} 
		finally {
			session.close();
		}
		return posteo;
	}
	
	/**
	 * Al ser Posteo una tabla formada con una clave Compuesta, envez de pasar la PK por parametro
	 * se pasa un objeto del tipo posteo q se desea realizar el update.
	 */
	@Override
	public boolean update(Object actualizado) {
		Posteo auxPostUpdate;
		try{
			auxPostUpdate= (Posteo) actualizado;
		}catch (ClassCastException e){
			System.out.println("ERROR: Error en el casteo de parametros");
			return false;
		}		
		boolean flag = true;
		session = HibernateUtil.getSessionFactory().openSession();
		transaction = null;
		System.out.println("Objeto a Actualizador antes try: "+auxPostUpdate);
		try {
			posteo = auxPostUpdate;
			transaction = session.beginTransaction();
			session.update( posteo );
			transaction.commit();
			} 
		catch (HibernateException e) {
			transaction.rollback();
			System.out.println("ERROR: Hibernate no puede realizar la actualizacion del Posteo");
			flag = false;
		} 
		finally {
			session.close();
		}
		return flag;
	}

	/**
	 * Al ser Posteo una tabla formada con una clave Compuesta, envez de pasar la PK por parametro
	 * se pasa un objeto del tipo posteo q se desea eliminar.
	 */
	@Override
	public boolean delete(Object remove) {
		Posteo delete;
		try{
			delete = (Posteo) remove;
		}catch(ClassCastException e){
			System.out.println("ERROR: No se puede castear el objeto a Posteo");
			return false;
		}
		boolean flag= true; 
		session = HibernateUtil.getSessionFactory().openSession();
		transaction = null;
		try {
			transaction = session.beginTransaction();
			posteo = (Posteo) session.get( Posteo.class, delete );
			if (posteo == null){
				return false;
			}
			session.delete(posteo);
			transaction.commit();
		} 
		catch (HibernateException e) {
			transaction.rollback();
			System.out.println("ERROR: Hibernate no puede realizar el borrado del Posteo");
			flag = false;
			} 
		finally {
			session.close();
			}
		return flag;
	}

	/**
	 * Al ser Posteo una tabla formada con una clave Compuesta, envez de pasar la PK por parametro
	 * se pasa un objeto del tipo posteo q se desea obtener.
	 */
	@Override
	public Object get(Object parametro) {
		Posteo key;
		try{
			key = (Posteo) parametro;
		}catch(ClassCastException e){
			System.out.println("ERROR: No se puede castear el objeto a Posteo");
			return null;
		}
		posteo = null;
		session = HibernateUtil.getSessionFactory().openSession();
		transaction = null;
		try {
			transaction = session.beginTransaction();
			posteo = (Posteo) session.get( Posteo.class, key );
			} 
		catch (	HibernateException e) {
			System.out.println("ERROR: MapPosteo.get() Hibernate no puede obtener el Posteo");
			return false;
		} 
		finally {
			session.close();
		}
		return posteo;
	}

	/**
	 * Recorre la base de datos en busca de todas los posteos que tiene grabadas relacionados con el Documento que se pasa por parametro 
	 * @param Documento a buscar posteos relacionados
	 * @return una lista con todas los documentos del sistema.
	 */
	public ArrayList<Posteo> obtenerPosteosRelacionados(Documento doc){
		session = HibernateUtil.getSessionFactory().openSession();
		Documento aBuscar = doc;
		ArrayList<Posteo> posteos = new ArrayList<Posteo>();
		try {
			 posteos = (ArrayList<Posteo>)session.createCriteria(Posteo.class).add( Restrictions.like("doc", aBuscar ) ).list();
			 System.out.println(posteos.get(0));
		} 
		catch (	HibernateException e) {
			System.out.println("ERROR: Hibernate no puede obtener los Posteos relacionados con el Doc");
			return null;
		} 
		finally {
			session.close();
		}
		return posteos;
	}
	
	/**
	 * Metodo que devuelve el MaxTf para un Vocabulario de la lista de Posteo
	 * @param voc a buscar su max Tf
	 * @return int con el valor de MaxTf, -1 en caso de fallar el metodo.
	 */
	public int Max_Tf(Vocabulario voc){
		session = HibernateUtil.getSessionFactory().openSession();
		Vocabulario aBuscar = voc;
		int maxTf = -1;
		try {
			ProjectionList projList = Projections.projectionList();
	        projList.add(Projections.max("term_frecuency"));
			maxTf = (Integer) session.createCriteria(Posteo.class).setProjection(projList).add(Restrictions.like("termino", aBuscar)).uniqueResult();
			System.out.println( maxTf);
		} 
		catch (	HibernateException e) {
			System.out.println("ERROR: Hibernate no puede obtener los Posteos relacionados con el Doc");
			return -1;
		} 
		finally {
			session.close();
		}
		return maxTf;
	}
	
	/**
	 * Buscar en posteo los R primeros posteos q contengan el max tf para ese termino
	 * @param voc a buscar
	 * @param nroDocRecuperar = R
	 * @return una lista con R Posteos o menos.
	 */
	public ArrayList<Posteo> MaxTFXVoc(Vocabulario voc, int nroDocRecuperar){
		ArrayList<Posteo> listaReturn = new ArrayList<Posteo>();
		if(voc == null || nroDocRecuperar <= 0){
			return null;
		}
		Vocabulario aBuscar = voc;
		int cant = nroDocRecuperar;
		try {
			session = HibernateUtil.getSessionFactory().openSession();
			Criteria criteria =session.createCriteria(Posteo.class)
					.add(Restrictions.like("termino", aBuscar))
					.addOrder(Order.desc("term_frecuency"));
			criteria.setMaxResults(cant);
			listaReturn = (ArrayList<Posteo>) criteria.list();
		} 
		catch (	HibernateException e) {
			System.out.println("ERROR: Hibernate no puede obtener los Posteos relacionados con el Voc");
			return null;
		} 
		finally {
			session.close();
		}
		return listaReturn;
	}

	@Override
	public boolean deleteAll() {
		session = HibernateUtil.getSessionFactory().openSession();
		transaction=null;
		try{
			String hql = "delete from Posteo";
			Query query = session.createQuery(hql);
			transaction = session.beginTransaction();
			query.executeUpdate();
			transaction.commit();
		}catch ( HibernateException e){
			System.out.println("ERROR: Hibernate no puede borrar todos los Posteos");
			transaction.rollback();
			return false;
		}
		finally{
			session.close();
		}
		return true;
	}
	
	
}
